package org.ccay.core.io;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;

/**
 * 虚拟文件系统 文件对象的抽象	
 */
public interface VFSFileObject {
	
	
	/**
	 * 获取存储类型
	 * 存储类型根据业务被抽象为3类
	 * 1、工作目录 2、归档目录 3、临时目录
	 * @return 获取存储类型
	 */
	FileStoreType getStoreType();
	
	/**
	 * 获取显示名称(如:文件下载时到客户流量器时用户看到的名称)
	 * @return
	 */
	String getDisplayName();
	
	/**
	 * 获取模块名称
	 * 虚拟文件系统被抽象为多个模块，每个模块可以定义自己独立的工作目录与归档目录，此方法返回模块名称。
	 *  {@link ModuleFileSystemConfig}
	 * @return 模块名称
	 */
	String getModule();
	/**
	 * 获取基本名称 
	 * 基本名称是文件名称的最后一个元素 例如 {@code /somefolder/somefile} 的基本名称是 {@code somefile}
     * <p>
     * 根路径是的基本名称时空字符串
     * </p>
	 * @return 基本名称 永远不返回null
	 */
	String getBaseName();
	
	/**
	 * 获取根路径
	 * 根路径根据模块不同其值不同，{@link ModuleFileSystemConfig}
	 * @return 根路径
	 */
	String getRootURI();
	
	/**
	 * 更具相对路径获取本地文件的绝对路径
	 * @return 本地绝对路径 relativePath 为空返回跟路径 归档文件或临时文件尝试调用时抛出异常
	 */
	String getLocalAbsolutePath();
	
	/**
	 * 更具相对路径获取本地工作目录的绝对路径
	 * @return 本地绝对路径 relativePath 为空返回跟路径 归档文件或临时文件尝试调用时抛出异常
	 */
	String getLocalRootAbsolutePath();
	/**
	 * 根据文件系统，返回文件的绝对路径。
	 * 路径中使用{@code /} 并且总是以{@code /}开头
	 * @return 绝对路径 永远不返回null
	 */
	String getAbsolutePath();
	
	/**
	 * 获取相对路径
	 * 相对路径是文件系统无关的路径，与跟路径一起组成了文件的绝对路径
	 * 根路径有[scheme://]/{模块定义的根路径}/appName/组成
	 * 
	 * @return
	 */
	String getRelativePath();
	/**
	 * 获取文件扩展名
	 * 
	 * @return 文件扩展名，如果文件名没有扩展名，返回空字符串 
	 */
	String getExtension();
	
	/**
	 * 获取此文件URI的scheme
	 * @return 此文件URI的scheme
	 */
	String getScheme();
	
	/**
	 * 获取此文件URI
	 * @return 此文件的URI
	 */
	String getURI();
	
	/**
	 * 是否是文件 依赖{@link #getType} 是否返回 {@link #FILETYPE_FILE}; 
	 * @return 是否是文件
	 */
	boolean isFile();
	
	/**
	 * 是否是目录 依赖{@link #getType} 是否返回 {@link #FILETYPE_FOLDER}; 
	 * @return 是否是目录
	 */
	boolean isFolder();
	
	/**
	 * 判断文件是否存在
	 * @return 文件是否存在
	 */
	boolean exists();
	
	
	/**
	 * 内容类型
	 * @return 内容类型
	 */
	String getContentType();
	
	/**
	 * 获取文件大小（字节）
	 * @return
	 */
	long getSize();

	/**
	 * 获取文件最后修改时间
	 * @return
	 */
	Date getLastModifiedTime();
	
	
	/**
	 * 获取文件输入流
	 * <p>任何时候，只能打开一个文件的输入流或输出流（输入输出流不能同时打开）
	 * <p> 使用结束后像其他流一样需要关闭，{@link #close} 将关闭文件，并关闭所有已经打开的流
	 * @return 文件输入流，此流在子类中应该是缓存的，因此在外层不需要在包装为{@code BufferedInputStream}.
	 */
	InputStream getInputStream();
	
	/**
	 * 获取文件输出流
	 * <p> 如果此文件不存在，此方法将创建他，并返回输出流
	 * <p>任何时候，只能打开一个文件的输入流或输出流（输入输出流不能同时打开）
	 * <p> 使用结束后像其他流一样需要关闭，{@link #close} 将关闭文件，并关闭所有已经打开的流
	 * @return 文件输出流 此流在子类中应该是缓存的，因此在外层不需要在包装为{@code BufferedOutputStream}.
	 */
	OutputStream getOutputStream();
	
	/**
	 * 是否在下载时字段关联客户端程序并且打开.
	 * @return 在下载时字段关联客户端程序并且打开.
	 */
	boolean isInline();
	/**
	 * 关闭文件，并关闭与此文件关联的所有资源，包括输入输出流。对于输出流将字段flush提交文件变更。
	 */
	void close();

	/**
	 * 将文件复制到归档目录 并返回关联到归档文件的VFSFileObject对象
	 * @return 关联到归档文件的VFSFileObject对象 如果当前对象是归档文档VFSFileObject 则返回this
	 */
	public VFSFileObject copyToArchive();
	
	/**
	 * 将文件复制到工作目录 并返回关联到工作目录的VFSFileObject对象
	 * @return 关联到工作文件的VFSFileObject对象 如果当前对象是工作文件的VFSFileObject 则返回this
	 */
	public VFSFileObject copyToWork();
	
	/**
	 * 将文件复制到临时目录
	 * @return 关联到临时文件的VFSFileObject对象 如果当前对象是临时文件VFSFileObject 则返回this
	 */
	public VFSFileObject copyToTemp();
	
	/**
	 * 删除文件
	 * @return 是否删除成功
	 */
	public boolean delete();
	
	/**
	 * 删除文件
	 * @return 是否删除成功
	 */
	public int deleteAll();
	
}
